﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using PloobsEngine;
using Microsoft.Xna.Framework;

namespace Etapa1.SofRender
{    
    public delegate Color PerformAlphaBlending(Color inBuffer, Color calculatedNow);    

    public class OutputMerger
    {
        Texture2D screenTexture;
        Color[] screen;
        float[] depth;
        bool depthTestEnable = true;
        Texture2D renderTarget = null;
        Texture2D activeTarget;
        Vector2 resolution;
        bool depthWrite = true;
        PerformAlphaBlending performAlphaBlending;
        bool alphaBlending = false;

        public PerformAlphaBlending PerformAlphaBlending
        {
            get { return performAlphaBlending; }
            set { performAlphaBlending = value; }
        }
        

        public bool AlphaBlending
        {
            get { return alphaBlending; }
            set { alphaBlending = value; }
        }

        public bool DepthWrite
        {
            get { return depthWrite; }
            set { depthWrite = value; }
        }

        internal Vector2 Resolution
        {
            get { return resolution; }
            set { resolution = value; }
        }

        public bool DepthTestEnable
        {
            get { return depthTestEnable; }
            set { depthTestEnable = value; }
        }

        public bool DepthTest(int x, int y, float z)
        {
            if (depthTestEnable)
            {
                if (depth[ y * ((int)resolution.X )+ x ] <= z)
                {
                    return false;
                }                
            }
            return true;
        }

        public OutputMerger(Vector2 res)
        {
            this.resolution = res;
            screenTexture = new Texture2D(EngineStuff.GraphicsDevice, (int)res.X, (int)res.Y);
            screen = new Color[(int)res.X * (int)res.Y];
            depth = new float[(int)res.X * (int)res.Y];
            activeTarget = screenTexture;
        }

        internal void SetPixel(int x, int y, float z, Color color)
        {
            if (DepthTest(x, y, z))
            {
                if (alphaBlending)
                {
                    screen[(y ) * ((int)resolution.X) + x ] = performAlphaBlending(screen[(y ) * ((int)resolution.X) + x ], color);
                    
                }
                else
                {
                    screen[(y ) * ((int)resolution.X) + x ] = color;
                }

                if (depthWrite)
                {
                    depth[(y ) * ((int)resolution.X) + x ] = z;
                }
            }
        }        

        public void SetRenderTarget(Texture2D renderTarget)
        {
            if (renderTarget == null)
            {
                this.renderTarget = null;
                activeTarget = screenTexture;
            }
            else
            {
                this.renderTarget = renderTarget;
                activeTarget = renderTarget;
            }
        }

        public Texture2D getTexture()
        {
            if (renderTarget == activeTarget)
            {
                SetRenderTarget(null);
            }
            return this.renderTarget;
        }

        public void Clear(Color color)
        {
            for (int i = 0; i < screen.Count(); i++)
            {
                screen[i] = color;
            }
        }

        public void Clear(Color color, float depth)
        {
            for (int i = 0; i < screen.Count(); i++)
            {
                screen[i] = color;
                this.depth[i] = depth;
            }
        }
        
        internal void Draw()
        {
            EngineStuff.GraphicsDevice.Textures[0] = null;
            screenTexture.SetData<Color>(screen);
            //screenTexture.Save("teste.png", ImageFileFormat.Png);

            EngineStuff.SpriteBatch.Begin();
            EngineStuff.SpriteBatch.Draw(screenTexture, EngineStuff.GetFullScreenRectangle(), Color.White);
            EngineStuff.SpriteBatch.End();

        }


    }
}
